home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / keybind / keytab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  38.2 KB  |  1,719 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #define KEYTAB_C
  9.  
  10. #include "keybind.h"
  11. #include <h/rcformat.h>
  12. #include <h/envvar_str.h>
  13. #include <lib/ori_rc_lib.h>
  14. #include <lib/ori_add_lib.h>
  15. /*}}}  */
  16.  
  17. /*{{{  overload prefix handling*/
  18. typedef struct overload_entry
  19.  { char *name;
  20.    int len;
  21.    struct overload_entry *next;
  22.  } overload_entry;
  23. private overload_entry *overloads=0;
  24.  
  25. /*{{{  overload_prefix*/
  26. public void overload_prefix(void)
  27. {
  28.   begin_parse();
  29.   for (;;)
  30.    { switch (get_full_token())
  31.       { case END: break;
  32.         /*{{{  NAME: a new mode*/
  33.         case NAME:
  34.          { overload_entry *x;
  35.            /*{{{  check, if conflicting*/
  36.            { int l;
  37.              for (x=overloads,l=ustrlen(tk_string);x;x=x->next)
  38.                 if (!strncmp((char*)tk_string,x->name,(x->len<l)?x->len:l))
  39.                    m_exit(F_OVER_CON,tk_string,x->name);
  40.            }
  41.            /*}}}  */
  42.            /*{{{  new node*/
  43.            x=kbd_malloc(sizeof(overload_entry)+ustrlen(tk_string)+1);
  44.            strcpy(x->name=(char*)(x+1),(char*)tk_string);
  45.            x->len=ustrlen(tk_string);
  46.            x->next=overloads;
  47.            overloads=x;
  48.            if (verbose_level>0)
  49.               fprintf(stderr,F_OVER_PRE,tk_string);
  50.            /*}}}  */
  51.            continue;
  52.          }
  53.         /*}}}  */
  54.         /*{{{  error*/
  55.         default:
  56.            m_exit(M_OVER_ERR);
  57.         /*}}}  */
  58.       }
  59.      break;
  60.    }
  61.   end_parse(M_WANTEND);
  62. }
  63. /*}}}  */
  64. /*{{{  cut_overload*/
  65. public unsigned char const *cut_overload(unsigned char const *name)
  66. { overload_entry *x;
  67.  
  68.   for (x=overloads;x;x=x->next)
  69.      if (!strncmp((char*)name,x->name,x->len))
  70.         return(name+x->len);
  71.  
  72.   return(name);
  73. }
  74. /*}}}  */
  75. /*}}}  */
  76. /*{{{  mouse handling*/
  77. typedef struct
  78.  { unsigned char* name;
  79.    unsigned char* code;
  80.    int code_lg;
  81.  } mouse_supports;
  82. private boolean mouse=False;
  83. private mouse_supports m_list[]=
  84.  /*{{{  init values*/
  85.  { {(unsigned char*)"scann",(unsigned char*)0,0},
  86. #   ifdef XTERM
  87.       { (unsigned char*)XTERM_MOUSE_NAME,(unsigned char*)XTERM_MOUSE_CODE,XTERM_MOUSE_LG },
  88. #   endif
  89. #   ifdef MGR
  90.       { (unsigned char*)MGR_MOUSE_NAME,(unsigned char*)MGR_MOUSE_CODE,MGR_MOUSE_LG },
  91. #   endif
  92. #   ifdef OS_MOUSE_TAG
  93.       { (unsigned char*)OS_MOUSE_NAME,(unsigned char*)OS_MOUSE_CODE,OS_MOUSE_LG },
  94. #   endif
  95.    { (unsigned char*)NO_MOUSE,(unsigned char*)0,0 },
  96.    { (unsigned char*)0,(unsigned char*)0,0 }
  97.  };
  98.  /*}}}  */
  99. public unsigned char *m_name=(unsigned char*)DEFAULT_MOUSE;
  100.  
  101. /*{{{  init_mouse*/
  102. private void init_mouse(void)
  103. { mouse_supports *x=m_list;
  104.  
  105.   do
  106.      if (!strncmp((char*)x->name,(char*)m_name,ustrlen(x->name)))
  107.         return;
  108.   while ((x++)->name);
  109.  
  110.   /*{{{  error exit*/
  111.   fprintf(stderr,"unknown mouse set\n");
  112.   fprintf(stderr,M_MICE);
  113.   show_mice(stderr);
  114.   fputc('\n',stderr);
  115.   kbd_exit(1);
  116.   /*}}}  */
  117. }
  118. /*}}}  */
  119. /*{{{  show_mice*/
  120. public void show_mice(FILE *f)
  121. { mouse_supports *x=m_list;
  122.   boolean first=True;
  123.  
  124.   fprintf(f,"%s(",m_name);
  125.   while (x->name) { fprintf(f,first?"%s":",%s",(x++)->name);first=False; }
  126.   fprintf(f,")");
  127. }
  128. /*}}}  */
  129. /*{{{  mouse_code*/
  130. public void mouse_code(void)
  131. { tokens token;
  132.   int i=0;
  133.   TOKEN map[MAX_MOUSE_BUTTONS];
  134.  
  135.   /*{{{  multiple mouse?*/
  136.   if (mouse)
  137.      m_exit(M_MOUSE);
  138.   mouse=True;
  139.   /*}}}  */
  140.   while ((token=get_full_token())!=END)
  141.    /*{{{  handle a button*/
  142.    { if (token==OPCODE)
  143.       /*{{{  opcode*/
  144.       { if ((map[i]=tk_key->num)!=O_NOP)
  145.            write_bind
  146.             ( tk_key->name,
  147.               (unsigned char*)(REF_COUNT_BASE+i),
  148.               mouse_kbd
  149.             );
  150.       }
  151.       /*}}}  */
  152.      else if (token==MACRO && ustrlen(tk_string)==1)
  153.       /*{{{  simple*/
  154.       { unsigned char simple[3];
  155.  
  156.         simple[0]='\"';
  157.         simple[1]=map[i]=tk_string[0];
  158.         simple[2]='\0';
  159.         write_bind
  160.          ( simple,
  161.            (unsigned char*)(REF_COUNT_BASE+i),
  162.            mouse_kbd
  163.          );
  164.       }
  165.       /*}}}  */
  166.      else if (token==OPERATION)
  167.       /*{{{  operation*/
  168.       { TOKEN k;
  169.  
  170.         if (tk_operation->place>=0)
  171.            k=(TOKEN)((int)O_EXE_MACRO+tk_operation->place);
  172.         else if (tk_operation->length==1)
  173.            k=tk_operation->ops[0];
  174.         else
  175.            m_exit(M_NODEBOUND);
  176.         if ((map[i]=k)!=O_NOP)
  177.            write_bind
  178.             ( tk_operation->op_name,
  179.               (unsigned char*)(REF_COUNT_BASE+i),
  180.               mouse_kbd
  181.             );
  182.       }
  183.       /*}}}  */
  184.      else
  185.       /*{{{  error*/
  186.         m_exit(M_NOCOMMAND);
  187.       /*}}}  */
  188.      if (++i==MAX_MOUSE_BUTTONS)
  189.       /*{{{  memory-crash*/
  190.         m_exit(M_NOMEMORY);
  191.       /*}}}  */
  192.    }
  193.    /*}}}  */
  194.   write_buttons_rc(map,i);
  195. }
  196. /*}}}  */
  197. /*}}}  */
  198. /*{{{  alias handling*/
  199. /*{{{  ALIAS_LIST*/
  200. typedef struct ALIAS_LIST
  201.  { const unsigned char *key_name;
  202.    struct acl
  203.     { int length;
  204.       struct acl *next;
  205.       TOKEN codes[1];
  206.     } *code;
  207.    struct ALIAS_LIST *next;
  208.  } ALIAS_LIST;
  209. /*}}}  */
  210. private const ALIAS_LIST init_al_list={ undef,0,0 };
  211. private ALIAS_LIST *alias_list=(ALIAS_LIST*)&init_al_list;
  212.  
  213. /*{{{  create an alias entry*/
  214. private void creat_alias(unsigned char *name,int lg,TOKEN *code)
  215. { ALIAS_LIST *ap;
  216.  
  217.   for (ap=alias_list;;ap=ap->next)
  218.      if (!ap)
  219.       /*{{{  unknown alias -> new node*/
  220.       {
  221.         /*{{{  new node at head of alias list*/
  222.         ap=kbd_malloc(sizeof(ALIAS_LIST));
  223.         ap->next=alias_list;
  224.         alias_list=ap;
  225.         /*}}}  */
  226.         /*{{{  no sequences till now*/
  227.         ap->code=0;
  228.         /*}}}  */
  229.         /*{{{  name in node*/
  230.         ap->key_name=mstrcpy(name);
  231.         /*}}}  */
  232.         break;
  233.       }
  234.       /*}}}  */
  235.      else if (!ustrcmp(name,ap->key_name))
  236.       /*{{{  break, alias uses more than one sequence*/
  237.       { if (warning)
  238.          { error_po();
  239.            fprintf(stderr,F_2ALIAS,name);
  240.          }
  241.         break;
  242.       }
  243.       /*}}}  */
  244.   /*{{{  code in node*/
  245.   { struct acl *x;
  246.  
  247.     x=kbd_malloc(sizeof(struct acl)+(lg-1)*sizeof(TOKEN));
  248.     x->next=ap->code;
  249.     ap->code=x;
  250.     x->length=lg;
  251.     memcpy(x->codes,code,lg*sizeof(TOKEN));
  252.   }
  253.   /*}}}  */
  254.   if (verbose_level>1)
  255.      fprintf(stderr,F_ALIAS,name);
  256. }
  257. /*}}}  */
  258. /*{{{  init alias list*/
  259. public void init_alias(void)
  260. { TOKEN esc=033;
  261.  
  262.   creat_alias((unsigned char*)"esc",1,&esc);
  263. }
  264. /*}}}  */
  265. /*}}}  */
  266. /*{{{  keytables*/
  267. /*{{{  types*/
  268. /*{{{  KEY_LONG*/
  269. typedef struct kl_struct
  270.  { union
  271.     { int id;
  272.       struct kl_struct *hash;
  273.     } x;
  274.    TOKEN code;
  275.    TOKEN key;
  276.    struct kl_struct *next;
  277.    struct kl_struct *n_level;
  278.  } KEY_LONG;
  279. /*}}}  */
  280. /*{{{  TERMINALS*/
  281. typedef struct t_lst
  282.  { unsigned char tname[NAME_LG+1];
  283.    int id;
  284.    struct t_lst *next;
  285.  } TERMINALS;
  286. /*}}}  */
  287. /*{{{  KEYTABLE*/
  288. typedef struct kt
  289.  { int id;
  290.    unsigned char mode[NAME_LG+1];
  291.    boolean def;
  292.    struct ktbl
  293.     { TERMINALS *t;
  294.       KEY_LONG *top_level;
  295.       int mark;
  296.       struct ktbl *next;
  297.     } keys;
  298.    struct kt *next;
  299.  } KEYTABLE;
  300. /*}}}  */
  301. /*{{{  KEYSEQUENCE*/
  302. typedef struct
  303.  { unsigned char protocol[NAME_LG+1];
  304.    struct ksl
  305.     { TERMINALS *t;
  306.       int lg;
  307.       TOKEN codes[ALIAS_LG];
  308.       struct ksl *next;
  309.     } *key_list;
  310.  } KEYSEQUENCE;
  311. /*}}}  */
  312. /*}}}  */
  313. /*{{{  variables*/
  314. /* do not change DEF_TERM, origami needs the empty word for detecting */
  315. /* the default table! */
  316. /* do not change DEF_MODE_ID, origami uses this table as startup table! */
  317. #define DEF_TERM ""
  318. #define DEF_TERM_ID 0
  319. #define DEF_MODE ""
  320. #define DEF_MODE_ID 0
  321.  
  322. private unsigned char const def_term_name[]=DEF_TERM;
  323. private TERMINALS const def_terminal={ DEF_TERM,DEF_TERM_ID,0 };
  324. private TERMINALS *term_list= (TERMINALS*)&def_terminal;
  325. private int last_used_term_id=DEF_TERM_ID;
  326.  
  327. private unsigned char const def_mode_name[]=DEF_MODE;
  328. private KEYTABLE *key_table_list=0;
  329. private int last_ktbl_id=DEF_MODE_ID;
  330.  
  331. private boolean ab_set=False;
  332. private boolean def_kbd_used=False;
  333. private int modes_used;
  334. private int bind_help_id=usr_kbd;
  335. /*}}}  */
  336.  
  337. /*{{{  struct ksl mallocing*/
  338. private struct ksl *ksl_f_list=0;
  339.  
  340. /*{{{  ks_malloc*/
  341. private struct ksl *ks_malloc(void)
  342. {
  343.   struct ksl *k;
  344.  
  345.   if ((k=ksl_f_list))
  346.      ksl_f_list=k->next;
  347.   else
  348.      k=kbd_malloc(sizeof(struct ksl));
  349.  
  350.   return(k);
  351. }
  352. /*}}}  */
  353. /*{{{  ks_free*/
  354. private void ks_free(struct ksl *kl)
  355. {
  356.   kl->next=ksl_f_list;
  357.   ksl_f_list=kl;
  358. }
  359. /*}}}  */
  360. /*{{{  ksl_free*/
  361. private void ksl_free(struct ksl *kl)
  362. {
  363.   for (;kl;)
  364.    { struct ksl *kl1;
  365.  
  366.      kl1=kl->next;
  367.      ks_free(kl);
  368.      kl=kl1;
  369.    }
  370. }
  371. /*}}}  */
  372. /*}}}  */
  373. /*{{{  TERMINALS mallocing*/
  374. private TERMINALS *t_f_list=0;
  375.  
  376. /*{{{  t_malloc*/
  377. private TERMINALS *t_malloc(void)
  378. {
  379.   TERMINALS *t;
  380.  
  381.   if ((t=t_f_list))
  382.      t_f_list=t->next;
  383.   else
  384.      t=kbd_malloc(sizeof(TERMINALS));
  385.  
  386.   return(t);
  387. }
  388. /*}}}  */
  389. /*{{{  t_free*/
  390. private void t_free(TERMINALS *t)
  391. {
  392.   t->next=t_f_list;
  393.   t_f_list=t;
  394. }
  395. /*}}}  */
  396. /*{{{  tl_free*/
  397. private void tl_free(TERMINALS *t)
  398. {
  399.   while (t)
  400.    { TERMINALS *tx;
  401.  
  402.      tx=t->next;
  403.      t_free(t);
  404.      t=tx;
  405.    }
  406. }
  407. /*}}}  */
  408. /*}}}  */
  409.  
  410. /*{{{  name2terminal*/
  411. private TERMINALS *name2terminal(unsigned char const * const term)
  412. {
  413.   TERMINALS *t;
  414.  
  415.   for (t=term_list;;t=t->next)
  416.      if (!t)
  417.       /*{{{  define new terminal*/
  418.       { t=t_malloc();
  419.         ustrcpy(t->tname,term);
  420.         t->id=++last_used_term_id;
  421.         t->next=term_list;
  422.         term_list=t;
  423.         break;
  424.       }
  425.       /*}}}  */
  426.      else if (!ustrcmp(term,t->tname))
  427.         break;
  428.  
  429.   return(t);
  430. }
  431. /*}}}  */
  432. /*{{{  name2mode*/
  433. private KEYTABLE *name2mode(unsigned char const*const s)
  434. {
  435.   KEYTABLE *x;
  436.  
  437.   for (x=key_table_list;;x=x->next)
  438.      if (!x || !ustrcmp(s,x->mode))
  439.         break;
  440.  
  441.   return(x);
  442. }
  443. /*}}}  */
  444. /*{{{  id2mode*/
  445. private KEYTABLE *id2mode(int id)
  446. {
  447.   KEYTABLE *x;
  448.  
  449.   for (x=key_table_list;;x=x->next)
  450.      if (!x)
  451.         m_exit(M_CRASH);
  452.      else if (id==x->id)
  453.         break;
  454.  
  455.   return(x);
  456. }
  457. /*}}}  */
  458. /*{{{  get_term_token*/
  459. private tokens get_term_token(void)
  460. { tokens x=get_full_token();
  461.  
  462.   switch (x)
  463.    { case DEFAULT:
  464.         ustrcpy(tk_string,def_mode_name);
  465.         x=NAME;
  466.         break;
  467.      case OPCODE:
  468.      case OPERATION:
  469.      case VARIABLE:
  470.         if (isalnum(tk_string[0]))
  471.            x=NAME;
  472.      default:
  473.         break;
  474.    }
  475.   return(x);
  476. }
  477. /*}}}  */
  478.  
  479. /*{{{  KEY_LONG node handling*/
  480. private KEY_LONG *k_freed=0;
  481.  
  482. /*{{{  key_alloc*/
  483. private KEY_LONG *key_alloc(void)
  484. {
  485.   KEY_LONG *x;
  486.  
  487.   if (k_freed)
  488.    /*{{{  use freed node*/
  489.    { x=k_freed;
  490.      k_freed=k_freed->next;
  491.    }
  492.    /*}}}  */
  493.   else
  494.    /*{{{  use new one*/
  495.    { static KEY_LONG *km;
  496.      static int key_malloced=0;
  497. #    define KEY_PAKET 128
  498.  
  499.      if (!key_malloced)
  500.       /*{{{  get paket of key structs*/
  501.       { km=kbd_malloc(KEY_PAKET*sizeof(KEY_LONG));
  502.         key_malloced=KEY_PAKET;
  503.       }
  504.       /*}}}  */
  505.      x=km++;
  506.      key_malloced--;
  507.    }
  508.    /*}}}  */
  509.   x->next=x->n_level=0;
  510.   x->code=x->key=0;
  511.  
  512.   return(x);
  513. }
  514. /*}}}  */
  515. /*{{{  key_free*/
  516. private void key_free(KEY_LONG * const x)
  517. {
  518.   x->next=k_freed;
  519.   k_freed=x;
  520. }
  521. /*}}}  */
  522. /*{{{  key_copy*/
  523. private KEY_LONG *key_copy(KEY_LONG *p)
  524. { KEY_LONG *n;
  525.  
  526.   if (!p)
  527.      return(0);
  528.   n=key_alloc();
  529.   *n = *p;
  530.   if (n->next)
  531.      n->next=key_copy(p->next);
  532.   if (n->n_level)
  533.       n->n_level=key_copy(p->n_level);
  534.  
  535.   return(n);
  536. }
  537. /*}}}  */
  538. /*}}}  */
  539.  
  540. /*{{{  init_ktb*/
  541. private struct ktbl *find_term(KEYTABLE * const k,TERMINALS const * const t);
  542.  
  543. private void init_ktb
  544.  ( unsigned char const*const mode,
  545.    unsigned char const*const term
  546.  )
  547. {
  548.   TERMINALS *t;
  549.   struct ktbl *kl;
  550.   KEYTABLE *x;
  551.  
  552.   for (x=key_table_list;;x=x->next)
  553.      if (!x)
  554.       /*{{{  get a new table for mode*/
  555.       {
  556.         /*{{{  get new space*/
  557.         x=kbd_malloc(sizeof(KEYTABLE));
  558.         x->next=key_table_list;
  559.         key_table_list=x;
  560.         /*}}}  */
  561.         x->id=last_ktbl_id++;
  562.         /*{{{  init data for the mode/default table*/
  563.         ustrcpy(x->mode,mode);
  564.         x->def=False;
  565.         x->keys.t=(TERMINALS*)&def_terminal;
  566.         x->keys.top_level=key_alloc();
  567.         x->keys.mark=bind_help_id++;
  568.         x->keys.next=0;
  569.         if (bind_help_id&0x8000)
  570.            m_exit(M_T_MAX);
  571.         /*}}}  */
  572.         break;
  573.       }
  574.       /*}}}  */
  575.      else if (!ustrcmp(mode,x->mode))
  576.         break;
  577.   for (t=name2terminal(term),kl= &x->keys;;kl=kl->next)
  578.      if (!kl)
  579.       /*{{{  define a new table for current terminal*/
  580.       { kl=kbd_malloc(sizeof(struct ktbl));
  581.         kl->t=t;
  582.         kl->top_level=key_copy
  583.                        ( find_term
  584.                           ( x,
  585.                             (TERMINALS*)&def_terminal
  586.                           )->top_level
  587.                        );
  588.         kl->mark=bind_help_id++;
  589.         kl->next=x->keys.next;
  590.         x->keys.next=kl;
  591.         break;
  592.       }
  593.       /*}}}  */
  594.      else if (kl->t->id==t->id)
  595.         break;
  596. }
  597. /*}}}  */
  598. /*{{{  find_term*/
  599. private struct ktbl *find_term(KEYTABLE * const k,TERMINALS const * const t)
  600. {
  601.   struct ktbl *x;
  602.  
  603.   for (x= &k->keys;;x=x->next)
  604.      if (!x)
  605.       { init_ktb(k->mode,t->tname);
  606.         x=find_term(k,t);
  607.         break;
  608.       }
  609.      else if (x->t->id==t->id)
  610.         break;
  611.  
  612.   return(x);
  613. }
  614. /*}}}  */
  615.  
  616. /*{{{  init_keytables*/
  617. public void init_keytables(void)
  618. {
  619.   init_mouse();
  620.   init_ktb(def_mode_name,def_term_name);
  621. }
  622. /*}}}  */
  623. /*{{{  token2mode*/
  624. public int token2mode(tokens t)
  625. {
  626.   KEYTABLE *k;
  627.  
  628.   if (t!=OPERATION || !(k=name2mode((unsigned char const*const)tk_string)))
  629.      return(-1);
  630.   else
  631.      return(k->id);
  632. }
  633. /*}}}  */
  634.  
  635. /*{{{  define_k_modes*/
  636. public void define_k_modes(void)
  637. {
  638.   boolean begin_end_used=False;
  639.  
  640.   if (def_kbd_used)
  641.      m_exit(M_KBD_KEY);
  642.   for (;;)
  643.    { switch (get_full_token())
  644.       {
  645.         /*{{{  END:  end loop*/
  646.         case END:
  647.            break;
  648.         /*}}}  */
  649.         /*{{{  BEGIN:mark list read*/
  650.         case BEGIN:
  651.            if (begin_end_used)
  652.               goto mkbd_error;
  653.            begin_end_used=True;
  654.            continue;
  655.         /*}}}  */
  656.         /*{{{  NAME: a new mode*/
  657.         case NAME:
  658.          { int mode_number;
  659.  
  660.            /*{{{  set mode number*/
  661.            { KEYTABLE *k;
  662.  
  663.              k=name2mode(tk_string);
  664.              mode_number=k?k->id:-1;
  665.            }
  666.            /*}}}  */
  667.            if (mode_number==-1)
  668.             { KEYTABLE *k;
  669.  
  670.               if (modes_used)
  671.                  init_ktb(tk_string,def_term_name);
  672.               mode_number=modes_used;
  673.               k=id2mode(mode_number);
  674.               ustrcpy(k->mode,tk_string);
  675.               /*{{{  verbose?*/
  676.               if (verbose_level>0)
  677.                  fprintf(stderr,F_KBDS,k->mode,modes_used);
  678.               /*}}}  */
  679.               /*{{{  gen kbd switch macro*/
  680.               { TOKEN t[2];
  681.  
  682.                 t[0]=M_SW_KBD;
  683.                 t[1]=modes_used;
  684.                 verbose_level--;
  685.                 creat_op(k->mode,True,2,t,-1,False,0);
  686.                 verbose_level++;
  687.               }
  688.               /*}}}  */
  689.               /*{{{  maybe gen rc comment*/
  690.               if (commenting && !dest_mac)
  691.                { char buff[NAME_LG+NAME_LG];
  692.                  char *tp=buff;
  693.  
  694.                  sprintf(buff,"%s is mode %d",tk_string,mode_number);
  695.                  rc_put_c(RC_COMMENT,rc.fp);
  696.                  do rc_put_c(*tp,rc.fp); while (*tp++);
  697.                }
  698.               /*}}}  */
  699.               modes_used++;
  700.             }
  701.            continue;
  702.          }
  703.         /*}}}  */
  704.         /*{{{  error*/
  705.         default:
  706.         mkbd_error:
  707.            m_exit(M_KBD_ERR);
  708.         /*}}}  */
  709.       }
  710.      break;
  711.    }
  712.   if (begin_end_used)
  713.      end_parse(M_WANTEND);
  714. }
  715. /*}}}  */
  716. /*{{{  check_k_modes*/
  717. public void check_k_modes(void)
  718. {
  719.   int i;
  720.  
  721.   for (i=modes_used;i--;)
  722.    { KEYTABLE *k;
  723.  
  724.      k=id2mode(i);
  725.      if (!k->def)
  726.         m_exit(F_KBD_MISS,k->mode);
  727.    }
  728. }
  729. /*}}}  */
  730.  
  731. /*{{{  add_keyseq*/
  732. /*{{{  decode*/
  733. private unsigned char *decode(TOKEN keynumber)
  734. { KEYNAME *seek = bindings;
  735.   int off;
  736.   static unsigned char name[NAME_LG];
  737.  
  738.   /*{{{  store offset to first fix-macro*/
  739.   if (keynumber>=O_CALL_FIX)
  740.    { off=keynumber-O_CALL_FIX+1;
  741.      keynumber=O_CALL_FIX;
  742.    }
  743.   else
  744.      off=0;
  745.   /*}}}  */
  746.   while (seek->name)
  747.     if ((seek->num)==(TOKEN) keynumber)
  748.       /*{{{  return the name*/
  749.       if (off)
  750.        { sprintf((char*)name,"%d=%s %d",keynumber,seek->name,off);
  751.          return(name);
  752.        }
  753.       else
  754.        { sprintf((char*)name,"%d=%s",keynumber,seek->name);
  755.          return(name);
  756.        }
  757.       /*}}}  */
  758.     else
  759.       seek++;
  760.   sprintf((char*)name,F_NOKEYNUMBER,keynumber);
  761.   return(name);
  762. }
  763. /*}}}  */
  764. /*{{{  add_key*/
  765. private KEY_LONG *add_key(TOKEN key,KEY_LONG *current,TOKEN op)
  766. {
  767.   KEY_LONG *x;
  768.  
  769.   for (x=current->n_level;;x=x->next)
  770.      if (!x)
  771.       /*{{{  get new node*/
  772.       { x=key_alloc();
  773.         x->key=key;
  774.         x->next=current->n_level;
  775.         current->n_level=x;
  776.         break;
  777.       }
  778.       /*}}}  */
  779.      else if (x->key == key)
  780.       /*{{{  key already in list, end search or error*/
  781.       { if (x->code)
  782.            if (x->code==op)
  783.             /*{{{  maybe warn*/
  784.             { if (warning)
  785.                { error_po();
  786.                  fprintf(stderr,F_DBL_BIND,decode(op));
  787.                }
  788.             }
  789.             /*}}}  */
  790.            else
  791.             /*{{{  return error*/
  792.             { error_po();
  793.               fprintf(stderr,F_ISMASKED,decode(x->code));
  794.               x=0;
  795.             }
  796.             /*}}}  */
  797.         break;
  798.       }
  799.       /*}}}  */
  800.  
  801.   return (x);
  802. }
  803. /*}}}  */
  804. /*{{{  set_key_code*/
  805. private boolean set_key_code (TOKEN code,KEY_LONG *current)
  806. {
  807.   if (current->n_level)
  808.    { error_po();
  809.      fprintf(stderr,F_MASKS,decode(code));
  810.      return(True);
  811.    }
  812.   current->code = code;
  813.  
  814.   return (False);
  815. }
  816. /*}}}  */
  817.  
  818. private void add_keyseq(struct ktbl *kt,TOKEN k,int lg,TOKEN *s)
  819. { KEY_LONG *key_point;
  820.  
  821.   if (kt)
  822.    { key_point=kt->top_level;
  823.      for (;lg;lg--)
  824.         if (!(key_point=add_key(*s++,key_point,((lg>1)?0:k))))
  825.            goto error_out;
  826.      if (set_key_code(k,key_point))
  827.         goto error_out;
  828.    }
  829.   return;
  830. error_out:
  831.     m_exit
  832.      ( F_CUR_TERM,
  833.        kt->t->id==DEF_TERM_ID
  834.         ? (unsigned char*)"default"
  835.         : kt->t->tname
  836.      );
  837. }
  838. /*}}}  */
  839. /*{{{  parse_keysequence*/
  840. /*{{{  add_k_c*/
  841. private void add_k_c(struct ksl *k,TOKEN c)
  842. {
  843.   int l;
  844.  
  845.   if ((l=k->lg++)==ALIAS_LG)
  846.      m_exit(M_LONG_KEY);
  847.   k->codes[l]=c;
  848. }
  849. /*}}}  */
  850. /*{{{  add_kl_c*/
  851. private void add_kl_c(struct ksl *kl,TOKEN c)
  852. {
  853.   for (;kl;kl=kl->next)
  854.      add_k_c(kl,c);
  855. }
  856. /*}}}  */
  857. /*{{{  add_k_alias*/
  858. private struct ksl *add_k_alias(struct ksl *k,ALIAS_LIST *a)
  859. {
  860.   struct acl *c,*cn;
  861.  
  862.   for (c=a->code;;c=cn,k=k->next)
  863.    { cn=c->next;
  864.      if (cn)
  865.       /*{{{  double current sequence for next alias version*/
  866.       { struct ksl *x;
  867.  
  868.         x=ks_malloc();
  869.         *x = *k;
  870.         k->next=x;
  871.       }
  872.       /*}}}  */
  873.      /*{{{  append string*/
  874.      { TOKEN *s;
  875.        int  lg;
  876.  
  877.        for (lg=c->length,s=c->codes;lg;s++,lg--)
  878.           add_k_c(k,*s);
  879.      }
  880.      /*}}}  */
  881.      if (!cn)
  882.         return(k);
  883.    }
  884. }
  885. /*}}}  */
  886. /*{{{  add_kl_alias*/
  887. private void add_kl_alias(struct ksl *k,ALIAS_LIST *a)
  888. {
  889.   while (k)
  890.    { if (!(k=add_k_alias(k,a)))
  891.         kbd_exit(1);
  892.      k=k->next;
  893.    }
  894. }
  895. /*}}}  */
  896.  
  897. private void parse_keysequence(TERMINALS *t,KEYSEQUENCE *k)
  898. {
  899.   char *p;
  900.   tokens token;
  901.  
  902.   /*{{{  check for valid term*/
  903.   if (!t || t->id==-1)
  904.      t=0;
  905.   /*}}}  */
  906.   /*{{{  build empty KEYSEQUENCE list for given terms*/
  907.   { TERMINALS *tx;
  908.     struct ksl *kl;
  909.  
  910.     (p=(char*)k->protocol)[0]='\0';
  911.     for (tx=t,k->key_list=0;tx;tx=tx->next)
  912.      { kl=ks_malloc();
  913.        kl->t=tx;
  914.        kl->lg=0;
  915.        kl->next=k->key_list;
  916.        k->key_list=kl;
  917.      }
  918.   }
  919.   /*}}}  */
  920.   begin_parse();
  921.   for (;;)
  922.    { switch ((token=get_keycode_token()))
  923.       {
  924.         /*{{{  all*/
  925.         case MULT:
  926.            add_kl_c(k->key_list,keytaball);
  927.            strcat(p,"* ");
  928.            continue;
  929.         /*}}}  */
  930.         /*{{{  hex or normal char*/
  931.         case HEX:
  932.         case CHAR:
  933.            add_kl_c(k->key_list,tk_char);
  934.            /*{{{  generate protocol of this binding*/
  935.            if (token==HEX)
  936.             { strcat(p,(char*)tk_string);
  937.               strcat(p," ");
  938.             }
  939.            else if (tk_char==127)
  940.               strcat(p,"C-? ");
  941.            else if (tk_char==' ')
  942.               strcat(p,"space ");
  943.            else if ((unsigned int)tk_char>(unsigned int)' ')
  944.             { char x[3];
  945.  
  946.               x[0]=(char)tk_char;
  947.               x[1]=' ';
  948.               x[2]='\0';
  949.               strcat(p,x);
  950.             }
  951.            else
  952.             { char x[5];
  953.  
  954.               x[0]='C';
  955.               x[1]='-';
  956.               x[2]=CTRL_CHARS[tk_char];
  957.               x[3]=' ';
  958.               x[4]='\0';
  959.               strcat(p,x);
  960.             }
  961.            /*}}}  */
  962.            continue;
  963.         /*}}}  */
  964.         /*{{{  meta*/
  965.         case META:
  966.            add_kl_c(k->key_list,27);
  967.            strcat(p,"M-");
  968.            continue;
  969.         /*}}}  */
  970.         /*{{{  alias*/
  971.         case DOLLAR:
  972.          { ALIAS_LIST *ap;
  973.  
  974.            ap=alias_list;
  975.            while (ap && ustrcmp(ap->key_name,tk_string))
  976.               ap=ap->next;
  977.            if (ap)
  978.             /*{{{  alias found -> normal alias, copy to all sequences*/
  979.               add_kl_alias(k->key_list,ap);
  980.             /*}}}  */
  981.            else
  982.             /*{{{  handle as terminal-alias*/
  983.             { struct ksl *kl;
  984.  
  985.               for (kl=k->key_list;kl;)
  986.                { unsigned char an[NAME_LG];
  987.  
  988.                  /*{{{  create correct name*/
  989.                  ustrcpy(an,kl->t->tname);
  990.                  strcat((char*)an,"@");
  991.                  ustrcat(an,tk_string);
  992.                  /*}}}  */
  993.                  ap=alias_list;
  994.                  while (ap && ustrcmp(ap->key_name,an))
  995.                     ap=ap->next;
  996.                  if (ap)
  997.                   /*{{{  alias found*/
  998.                   { if (!(kl=add_k_alias(kl,ap)))
  999.                        kbd_exit(1);
  1000.                     kl=kl->next;
  1001.                   }
  1002.                   /*}}}  */
  1003.                  else
  1004.                   /*{{{  don't bind this term-alias!*/
  1005.                   { if (warning)
  1006.                      { error_po();
  1007.                        fprintf(stderr,F_MISALIAS,an);
  1008.                      }
  1009.                     if (kl==k->key_list)
  1010.                      { k->key_list=kl->next;
  1011.                        ks_free(kl);
  1012.                        kl=k->key_list;
  1013.                      }
  1014.                     else
  1015.                      { struct ksl *kx;
  1016.  
  1017.                        for (kx=k->key_list;;kx=kx->next)
  1018.                           if (kx->next==kl)
  1019.                            { kx->next=kl->next;
  1020.                              ks_free(kl);
  1021.                              kl=kx->next;
  1022.                              break;
  1023.                            }
  1024.                      }
  1025.                   }
  1026.                   /*}}}  */
  1027.                }
  1028.             }
  1029.             /*}}}  */
  1030.            strcat(p,(char*)tk_string);
  1031.            strcat(p," ");
  1032.            continue;
  1033.          }
  1034.         /*}}}  */
  1035.         /*{{{  )*/
  1036.         case END: break;
  1037.         /*}}}  */
  1038.         /*{{{  errors*/
  1039.         default:
  1040.            m_exit(M_WANTEND);
  1041.         case ERROR:
  1042.            kbd_exit(1);
  1043.         /*}}}  */
  1044.       }
  1045.      break;
  1046.    }
  1047. }
  1048. /*}}}  */
  1049. /*{{{  keydef_body*/
  1050. private void keydef_body(KEYTABLE *kt,TERMINALS *tl,boolean ab_allowed)
  1051. { KEYSEQUENCE k;
  1052.   TOKEN operation;
  1053.   unsigned char *n;
  1054.   struct ksl *kl;
  1055.  
  1056.   /*{{{  get binding object*/
  1057.   switch (get_full_token())
  1058.    { default:
  1059.      invalid_bind_object:
  1060.          m_exit(M_NOCOMMAND);
  1061.      /*{{{  OPCODE, use table values*/
  1062.      case OPCODE:
  1063.         n=(unsigned char*)tk_key->name;
  1064.         operation=tk_key->num;
  1065.         break;
  1066.      /*}}}  */
  1067.      /*{{{  MACRO, generate simple string from tk_string*/
  1068.      case MACRO:
  1069.         if (ustrlen(tk_string)==1)
  1070.          { static unsigned char simple_char_name[3];
  1071.  
  1072.            simple_char_name[0]='\"';
  1073.            simple_char_name[1]=tk_string[0];
  1074.            simple_char_name[2]='\0';
  1075.            operation=tk_macro[0];
  1076.            n=simple_char_name;
  1077.            break;
  1078.          }
  1079.         else
  1080.            goto invalid_bind_object;
  1081.      /*}}}  */
  1082.      /*{{{  OPERATION: use deffun or defmac value*/
  1083.      case OPERATION:
  1084.         if (tk_operation->place<0)
  1085.          { if (tk_operation->length!=1)
  1086.               m_exit(M_NODEBOUND);
  1087.            else
  1088.               operation= *(tk_operation->ops);
  1089.          }
  1090.         else
  1091.            operation=(TOKEN)((int)O_EXE_MACRO+tk_operation->place);
  1092.         n=tk_operation->op_name;
  1093.         break;
  1094.      /*}}}  */
  1095.      /*{{{  MINUS: key-not-bound*/
  1096.      case MINUS:
  1097.         operation=keytabknb;
  1098.         n=0;
  1099.         break;
  1100.      /*}}}  */
  1101.    }
  1102.   /*}}}  */
  1103.   /*{{{  get sequence*/
  1104.   parse_keysequence(tl,&k);
  1105.   end_parse(M_KEYEND);
  1106.   /*}}}  */
  1107.   if (operation==O_BREAK)
  1108.      if (ab_allowed)
  1109.       /*{{{  handle abort*/
  1110.       {
  1111.         /*{{{  incorrect sequence*/
  1112.         if
  1113.          (    !k.key_list
  1114.            || k.key_list->lg!=1
  1115.            || k.key_list->codes[0]>=O_NOP
  1116.            || k.key_list->codes[0]<'\0'
  1117.            || !n
  1118.          )
  1119.            m_exit(M_NOABORT);
  1120.         /*}}}  */
  1121.         /*{{{  double*/
  1122.         if (ab_set)
  1123.            m_exit(M_DUPAB);
  1124.         /*}}}  */
  1125.         general_abort_key=k.key_list->codes[0];
  1126.         write_bind(n,k.protocol,abort_kbd);
  1127.         ab_set=True;
  1128.       }
  1129.       /*}}}  */
  1130.      else
  1131.       /*{{{  error*/
  1132.         m_exit(M_KBD_KEY);
  1133.       /*}}}  */
  1134.   else
  1135.    /*{{{  normal key*/
  1136.    { if (ab_allowed)
  1137.         if (modes_used)
  1138.          /*{{{  multiple keytables used -> crash*/
  1139.            m_exit(M_KBD_KEY);
  1140.          /*}}}  */
  1141.         else
  1142.            def_kbd_used=True;
  1143.      /*{{{  copy all not already used terminal-trees*/
  1144.      for (kl=k.key_list;kl;kl=kl->next)
  1145.         find_term(kt,kl->t);
  1146.      /*}}}  */
  1147.      /*{{{  add sequence to trees*/
  1148.      for (kl=k.key_list;kl;kl=kl->next)
  1149.       { struct ktbl *ktb;
  1150.  
  1151.         ktb=find_term(kt,kl->t);
  1152.         add_keyseq(ktb,operation,kl->lg,kl->codes);
  1153.       }
  1154.      /*}}}  */
  1155.      if (n)
  1156.       /*{{{  write to helpfile*/
  1157.       { TERMINALS *tp;
  1158.  
  1159.         for (tp=term_list;tp;tp=tp->next)
  1160.            for (kl=k.key_list;kl;kl=kl->next)
  1161.             { if (kl->t->id==tp->id)
  1162.                { struct ktbl *ktb;
  1163.  
  1164.                  ktb=find_term(kt,kl->t);
  1165.                  write_bind(n,k.protocol,ktb->mark);
  1166.                  break;
  1167.                }
  1168.             }
  1169.       }
  1170.       /*}}}  */
  1171.    }
  1172.    /*}}}  */
  1173.   ksl_free(k.key_list);
  1174. }
  1175. /*}}}  */
  1176. /*{{{  terminal_body*/
  1177. private void terminal_body(KEYTABLE *ktb)
  1178. {
  1179.   TERMINALS *term_l;
  1180.   boolean no_mode_set;
  1181.  
  1182.   if (!ktb)
  1183.    { no_mode_set=True;
  1184.      ktb=id2mode(DEF_MODE_ID);
  1185.    }
  1186.   else
  1187.      no_mode_set=False;
  1188.   /*{{{  get correct terminals*/
  1189.   switch (get_term_token())
  1190.    { case NAME:
  1191.      case NUMBER:
  1192.       /*{{{  single terminal*/
  1193.         term_l=t_malloc();
  1194.         *term_l= *name2terminal(tk_string);
  1195.         term_l->next=0;
  1196.         break;
  1197.       /*}}}  */
  1198.      case BEGIN:
  1199.       /*{{{  list of terminals*/
  1200.       { for (term_l=0;;)
  1201.          { switch (get_term_token())
  1202.             { case END:
  1203.                  break;
  1204.               case NAME:
  1205.               case NUMBER:
  1206.                /*{{{  copy name*/
  1207.                { TERMINALS *x;
  1208.  
  1209.                  x=t_malloc();
  1210.                  *x= *name2terminal(tk_string);
  1211.                  x->next=term_l;
  1212.                  term_l=x;
  1213.                  continue;
  1214.                }
  1215.                /*}}}  */
  1216.               default:
  1217.                  goto term_expected;
  1218.             }
  1219.            break;
  1220.          }
  1221.         break;
  1222.        }
  1223.       /*}}}  */
  1224.      default:
  1225.      term_expected:
  1226.         m_exit(M_T_NAME);
  1227.    }
  1228.   if (verbose_level>3)
  1229.    /*{{{  show all opened terminals*/
  1230.    { TERMINALS *x;
  1231.  
  1232.      for (x=term_l;x && x->id!=-1;x=x->next)
  1233.         fprintf(stderr,F_T_START,x->tname);
  1234.    }
  1235.    /*}}}  */
  1236.   /*}}}  */
  1237.   for (;;)
  1238.    { switch (get_full_token())
  1239.       { case END:
  1240.            break;
  1241.         case BEGIN:
  1242.            switch (get_full_token())
  1243.             { case KEYDEF:
  1244.                  keydef_body(ktb,term_l,False);
  1245.                  continue;
  1246.               case KEYALIAS:
  1247.                  if (no_mode_set)
  1248.                   /*{{{  do the alias*/
  1249.                   { unsigned char name[NAME_LG+1];
  1250.                     KEYSEQUENCE k;
  1251.                     struct ksl *kl;
  1252.  
  1253.                     name_parse(name,M_EXPALIAS,True);
  1254.                     parse_keysequence(term_l,&k);
  1255.                     for (kl=k.key_list;kl;kl=kl->next)
  1256.                       { unsigned char tname[2*NAME_LG+1];
  1257.  
  1258.                         ustrcpy(tname,kl->t->tname);
  1259.                         strcat((char*)tname,"@");
  1260.                         ustrcat(tname,name);
  1261.                         if (ustrlen(tname)>NAME_LG)
  1262.                            m_exit(M_CRASH);
  1263.                         creat_alias(tname,kl->lg,kl->codes);
  1264.                       }
  1265.                     ksl_free(k.key_list);
  1266.                     end_parse(M_WANTEND);
  1267.                     continue;
  1268.                   }
  1269.                   /*}}}  */
  1270.               default:
  1271.                  break;
  1272.             }
  1273.         default:
  1274.             m_exit(M_KBD_BEGIN);
  1275.       }
  1276.      break;
  1277.    }
  1278.  tl_free(term_l);
  1279.  if (verbose_level>3)
  1280.   /*{{{  show all opened terminals*/
  1281.   { TERMINALS *x;
  1282.  
  1283.     for (x=term_l;x && x->id!=-1;x=x->next)
  1284.        fprintf(stderr,M_T_END,x->tname);
  1285.   }
  1286.   /*}}}  */
  1287. }
  1288. /*}}}  */
  1289. /*{{{  def_keybind_code*/
  1290. public void def_keybind_code(void)
  1291. {
  1292.   keydef_body(name2mode(def_mode_name),term_list,True);
  1293. }
  1294. /*}}}  */
  1295. /*{{{  set_alias*/
  1296. public void set_alias(void)
  1297. { unsigned char name[NAME_LG];
  1298.   KEYSEQUENCE k;
  1299.  
  1300.   name_parse(name,M_EXPALIAS,True);
  1301.   parse_keysequence((TERMINALS*)&def_terminal,&k);
  1302.   if (k.key_list)
  1303.      creat_alias(name,k.key_list->lg,k.key_list->codes);
  1304. }
  1305. /*}}}  */
  1306. /*{{{  mode_code*/
  1307. public void mode_code(void)
  1308. {
  1309.   tokens t;
  1310.   int mode_number;
  1311.   KEYTABLE *ktb;
  1312.  
  1313.   if (!modes_used)
  1314.      m_exit(M_KBD_KEY);
  1315.   /*{{{  get correct kbd-no*/
  1316.   if ((mode_number=token2mode(get_full_token()))<0)
  1317.      kbd_exit(1);
  1318.   ktb=id2mode(mode_number);
  1319.   if (mode_number && !ktb->def)
  1320.      init_ktb(ktb->mode,def_term_name);
  1321.   /*}}}  */
  1322.   if (verbose_level>0)
  1323.      fprintf(stderr,F_BEG_MODE,ktb->mode);
  1324.   ktb->def=True;
  1325.   while ((t=get_full_token())!=END)
  1326.      switch (t)
  1327.       { case BEGIN:
  1328.            switch(get_full_token())
  1329.             { case KEYDEF:
  1330.                  keydef_body(ktb,term_list,False);
  1331.                  break;
  1332.               case TERMINAL:
  1333.                  terminal_body(ktb);
  1334.                  break;
  1335.               default:
  1336.                  goto mode_error;
  1337.  
  1338.             }
  1339.            break;
  1340.         default:
  1341.         mode_error:
  1342.            m_exit(M_KBD_BEGIN);
  1343.       }
  1344.   if (verbose_level>0)
  1345.      fprintf(stderr,F_END_MODE,ktb->mode);
  1346. }
  1347. /*}}}  */
  1348. /*{{{  terminal_cmd*/
  1349. public void terminal_cmd(void)
  1350. {
  1351.   terminal_body(0);
  1352. }
  1353. /*}}}  */
  1354.  
  1355. /*{{{  write_kbds*/
  1356. /*{{{  write_t_ktbs*/
  1357. typedef enum { FAR_NEXT_KEY=O_NOP,WRITTEN_KEY,TOP_KEY } special_key;
  1358. #define BASE_ID 0
  1359. #define CLEARED_ID (BASE_ID-1)
  1360. private int joined;
  1361.  
  1362. /*{{{  opti_id_ktb*/
  1363. /*{{{  ktb_set_id*/
  1364. /*{{{  comment*/
  1365. /* genereate unique identifiers for all nodes, shared next-nodes will
  1366.  * lead to far-next-nodes, to gurantee, that next-nodes are directly
  1367.  * after their parent!
  1368.  * returns the number of used nodes!
  1369.  */
  1370. /*}}}  */
  1371. /*{{{  ktb_clear_id*/
  1372. private void ktb_clear_id(KEY_LONG * const n)
  1373. {
  1374.   if (n)
  1375.    { n->x.id=CLEARED_ID;
  1376.      ktb_clear_id(n->next);
  1377.      ktb_clear_id(n->n_level);
  1378.    }
  1379. }
  1380. /*}}}  */
  1381. /*{{{  rec_ktb_set_id*/
  1382. private int rec_ktb_set_id(KEY_LONG * const n,int base)
  1383. {
  1384.   if (base&0x8000)
  1385.      m_exit(M_TOOMANYKEYS);
  1386.   if (n && n->x.id==CLEARED_ID)
  1387.    { n->x.id=base++;
  1388.      if (n->next)
  1389.       { if (n->next->x.id!=CLEARED_ID)
  1390.          /*{{{  generate far-next-node*/
  1391.          { KEY_LONG *c;
  1392.  
  1393.            c=key_alloc();
  1394.            c->x.id=CLEARED_ID;
  1395.            c->key=FAR_NEXT_KEY;
  1396.            c->n_level=n->next;
  1397.            n->next=c;
  1398.            joined--;
  1399.          }
  1400.          /*}}}  */
  1401.         base=rec_ktb_set_id(n->next,base);
  1402.       }
  1403.      base=rec_ktb_set_id(n->n_level,base);
  1404.    }
  1405.  
  1406.   return(base);
  1407. }
  1408. /*}}}  */
  1409.  
  1410. private int ktb_set_id(KEY_LONG * const ktb)
  1411.  {
  1412.    ktb_clear_id(ktb);
  1413.    return(rec_ktb_set_id(ktb,BASE_ID));
  1414.  }
  1415. /*}}}  */
  1416. /*{{{  sort_ktb*/
  1417. private void sort_ktb(KEY_LONG * const n,boolean const full)
  1418.  {
  1419.    if (n)
  1420.     { if (full)
  1421.          sort_ktb(n->n_level,True);
  1422.       if (n->next)
  1423.        { if (full)
  1424.             sort_ktb(n->next,True);
  1425.          if
  1426.           (    n->key<TOP_KEY
  1427.             && (    n->key==keytaball
  1428.                  || (n->key>n->next->key && n->next->key!=keytaball)
  1429.                )
  1430.           )
  1431.           /*{{{  change nodes*/
  1432.           { KEY_LONG x;
  1433.  
  1434.             x = *n;
  1435.             *n = *(x.next);
  1436.             *(x.next) = x;
  1437.             x.next->next=n->next;
  1438.             n->next=x.next;
  1439.             sort_ktb(n->next,False);
  1440.           }
  1441.           /*}}}  */
  1442.        }
  1443.     }
  1444.  }
  1445. /*}}}  */
  1446. #ifndef NO_OPTI
  1447.    /*{{{  join_tree*/
  1448.    /* transform the keytable tree into an directed-acyclic-graph,
  1449.     * sharing common sub-trees
  1450.     */
  1451.    /*{{{  ktb hashing*/
  1452.    private KEY_LONG *hash[O_NOP];
  1453.  
  1454.    /*{{{  ktb_init_hash*/
  1455.    /*{{{  ktb_r_i_h*/
  1456.    private void ktb_r_i_h(KEY_LONG * const n)
  1457.     {
  1458.       if (n)
  1459.        { ktb_r_i_h(n->n_level);
  1460.          if (n->key>=0 && n->key<O_NOP)
  1461.           { n->x.hash=hash[n->key];
  1462.             hash[n->key]=n;
  1463.           }
  1464.          ktb_r_i_h(n->next);
  1465.        }
  1466.     }
  1467.    /*}}}  */
  1468.  
  1469.    private void ktb_init_hash(KEY_LONG * const n)
  1470.     {
  1471.       /*{{{  empty lists*/
  1472.       { int i;
  1473.  
  1474.         for (i=O_NOP;--i>=0;hash[i]=0);
  1475.       }
  1476.       /*}}}  */
  1477.       ktb_r_i_h(n);
  1478.     }
  1479.    /*}}}  */
  1480.    /*{{{  ktb_find_hash*/
  1481.    private KEY_LONG *ktb_find_hash(KEY_LONG const * const n)
  1482.     {
  1483.       KEY_LONG *x;
  1484.  
  1485.       if (n->key>=0 && n->key<O_NOP)
  1486.        { for (x=n->x.hash;x;x=x->x.hash)
  1487.             if
  1488.              (    x!=n
  1489.                && x->code==n->code
  1490.                && x->next==n->next
  1491.                && x->n_level==n->n_level
  1492.              )
  1493.                break;
  1494.        }
  1495.       else
  1496.          x=0;
  1497.  
  1498.       return(x);
  1499.     }
  1500.    /*}}}  */
  1501.    /*{{{  ktb_del_hash*/
  1502.    private void ktb_del_hash(KEY_LONG const * const n)
  1503.     {
  1504.       if (n->key>=0 && n->key<O_NOP)
  1505.          if (hash[n->key]==n)
  1506.             hash[n->key]=n->x.hash;
  1507.          else
  1508.           { KEY_LONG *x;
  1509.  
  1510.             for (x=hash[n->key];x;x=x->x.hash)
  1511.                if (x->x.hash==n)
  1512.                 { x->x.hash=n->x.hash;
  1513.                   break;
  1514.                 }
  1515.           }
  1516.     }
  1517.    /*}}}  */
  1518.    /*}}}  */
  1519.    /*{{{  rec_join_tree*/
  1520.    private boolean rec_join_tree(KEY_LONG * const n)
  1521.     {
  1522.       boolean ret;
  1523.  
  1524.       ret=False;
  1525.       if (n)
  1526.        { KEY_LONG *c;
  1527.  
  1528.          /*{{{  maybe use copy of n_level node*/
  1529.          if (n->n_level)
  1530.           { ret=rec_join_tree(n->n_level);
  1531.             if ((c=ktb_find_hash(n->n_level)))
  1532.              { ktb_del_hash(n->n_level);
  1533.                key_free(n->n_level);
  1534.                n->n_level=c;
  1535.                joined++;
  1536.                ret=True;
  1537.              }
  1538.           }
  1539.          /*}}}  */
  1540.          /*{{{  maybe use copy of next node*/
  1541.          if (n->next)
  1542.           { ret|=rec_join_tree(n->next);
  1543.             if ((c=ktb_find_hash(n->next)))
  1544.              /*{{{  replace next by found copy*/
  1545.              { ktb_del_hash(n->next);
  1546.                key_free(n->next);
  1547.                n->next=c;
  1548.                joined++;
  1549.                ret=True;
  1550.              }
  1551.              /*}}}  */
  1552.           }
  1553.          /*}}}  */
  1554.        }
  1555.       return(ret);
  1556.     }
  1557.    /*}}}  */
  1558.  
  1559.    private void join_tree(KEY_LONG * const ktb)
  1560.     {
  1561.       joined=0;
  1562.       ktb_init_hash(ktb);
  1563.       while (rec_join_tree(ktb));
  1564.     }
  1565.    /*}}}  */
  1566. #endif
  1567.  
  1568. private int opti_id_ktb(KEY_LONG * const ktb)
  1569.  {
  1570.    joined=0;
  1571.    /*{{{  set top_level key's to special values, and sort level entries*/
  1572.    { KEY_LONG *t;
  1573.      int m;
  1574.  
  1575.      for (m=TOP_KEY,t=ktb;t;t->key=m,m++,t=t->next)
  1576.         sort_ktb(t->n_level,True);
  1577.    }
  1578.    /*}}}  */
  1579. #  ifndef NO_OPTI
  1580.       join_tree(ktb);
  1581. #  endif
  1582.  
  1583.    return(ktb_set_id(ktb));
  1584.  }
  1585. /*}}}  */
  1586. /*{{{  write_single_keynode*/
  1587. private void write_single_keynode(KEY_LONG *n)
  1588.  {
  1589.    if (n && n->key!=WRITTEN_KEY && !dest_mac)
  1590.     { if (ab_set && n->key==general_abort_key)
  1591.          m_exit(M_ABORTUSED);
  1592.       /*{{{  create and write compressed keytab node*/
  1593.       { KEY ks;
  1594.  
  1595.         ks.flags=NOT_USED;
  1596.         ks.code=n->code;
  1597.         if (n->key==keytaball)
  1598.          { ks.key='\0';
  1599.            ks.flags|=MAGIC_KEY;
  1600.          }
  1601.         else
  1602.            ks.key=n->key;
  1603.         if (n->next)
  1604.            ks.flags|=NEXT_USED;
  1605.         if (n->n_level)
  1606.          { ks.flags|=LEVEL_USED;
  1607.            if (n->key==FAR_NEXT_KEY)
  1608.             { ks.flags|=FAR_NEXT;
  1609.               ks.key=0;
  1610.             }
  1611.            ks.code=n->n_level->x.id-n->x.id;
  1612.          }
  1613.         put_key_data(&ks,rc.fp);
  1614.       }
  1615.       /*}}}  */
  1616.       n->key=WRITTEN_KEY;
  1617.       write_single_keynode(n->next);
  1618.       write_single_keynode(n->n_level);
  1619.     }
  1620.  }
  1621. /*}}}  */
  1622.  
  1623. private void write_t_ktbs(TERMINALS const * const t)
  1624.  {
  1625.    KEY_LONG *top,*tail;
  1626.    int nodes;
  1627.  
  1628.    /*{{{  generate single tree for all modes*/
  1629.    { int m;
  1630.      for (top=0,m=0;m<modes_used;m++)
  1631.       { KEYTABLE const *k;
  1632.         struct ktbl *x;
  1633.  
  1634.         /*{{{  get ktbl for mode/terminal, adding mouse keys*/
  1635.         k=id2mode(m);
  1636.         x=find_term((KEYTABLE*)k,t);
  1637.         /*{{{  add mouse for this terminal*/
  1638.         { mouse_supports *m_ptr;
  1639.           unsigned char const *m_n;
  1640.  
  1641.           /*{{{  m_ptr=current mouse, or default*/
  1642.           for (m_ptr=m_list,m_n=(t->id!=DEF_TERM_ID)?t->tname:m_name;;)
  1643.            { if
  1644.               (    m_ptr->name
  1645.                 && strncmp((char*)m_ptr->name,(char*)m_n,ustrlen(m_ptr->name))
  1646.               )
  1647.                 m_ptr++;
  1648.              else if (!(m_ptr->name) && (m_n==t->tname))
  1649.               { m_n=m_name;m_ptr=m_list; }
  1650.              else
  1651.                 break;
  1652.            }
  1653.           /*}}}  */
  1654.           if
  1655.            (    m_ptr
  1656.              && m_ptr->code_lg
  1657.            )
  1658.            { TOKEN codes[ALIAS_LG];
  1659.              int i;
  1660.  
  1661.              for (i=0;i<m_ptr->code_lg;i++)
  1662.                 codes[i]=m_ptr->code[i];
  1663.              add_keyseq(x,K_MOUSE,m_ptr->code_lg,codes);
  1664.            }
  1665.         }
  1666.         /*}}}  */
  1667.         /*}}}  */
  1668.         /*{{{  append to tree for mode*/
  1669.         if (top)
  1670.            tail->next=x->top_level;
  1671.         else
  1672.            top=x->top_level;
  1673.         tail=x->top_level;
  1674.         /*}}}  */
  1675.       }
  1676.    }
  1677.    /*}}}  */
  1678.    nodes=opti_id_ktb(top);
  1679.    /*{{{  write the keytable*/
  1680.    rc_put_c(RC_DEFKEY,rc.fp);
  1681.    /*{{{  write name*/
  1682.    { unsigned char const *term;
  1683.  
  1684.      term=t->tname;
  1685.      do
  1686.         rc_put_c(*term,rc.fp);
  1687.      while (*term++);
  1688.    }
  1689.    /*}}}  */
  1690.    rc_put_w(nodes,rc.fp);
  1691.    /*{{{  write help marks*/
  1692.    { int m;
  1693.  
  1694.      for (m=0;m<modes_used;m++)
  1695.         rc_put_w(find_term(id2mode(m),t)->mark,rc.fp);
  1696.    }
  1697.    /*}}}  */
  1698.    if (verbose_level>0)
  1699.       fprintf(stderr,F_NODES,t->tname,nodes,joined);
  1700.    write_single_keynode(top);
  1701.    /*}}}  */
  1702.  }
  1703. /*}}}  */
  1704.  
  1705. public void write_kbds(void)
  1706.  {
  1707.    TERMINALS *t;
  1708.  
  1709.    if (def_kbd_used)
  1710.       modes_used=1;
  1711.    ktb_count=modes_used;
  1712.    for (t=term_list;t;t=t->next)
  1713.       if (t->id!=DEF_TERM_ID)
  1714.          write_t_ktbs(t);
  1715.    write_t_ktbs(&def_terminal);
  1716.  }
  1717. /*}}}  */
  1718. /*}}}  */
  1719.